package com.bdbit.ChargingStation.services;

import com.bdbit.ChargingStation.Enum.OrderStatus;
import com.bdbit.ChargingStation.Utils.GsonUtils;
import com.bdbit.ChargingStation.Utils.HttpClientUtil;
import com.bdbit.ChargingStation.Utils.TimeUtils;
import com.bdbit.ChargingStation.controller.ChargingOrderController;
import com.bdbit.ChargingStation.entity.ChargingOrder;
import com.bdbit.ChargingStation.entity.OrderEntity;
import com.bdbit.ChargingStation.entity.bean_base_order;
import com.bdbit.ChargingStation.repository.ChargingOrderRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.lang.Thread.sleep;

@Slf4j
@Service
public class OrderProcessingService {

    private final HttpClientUtil httpClientUtil;
    @Autowired
    private OrderService orderService;
    @Autowired
    private PaymentService paymentService; // 注入 PaymentService
    @Autowired
    ChargingOrderService chargingOrderService;
    @Autowired
    private ChargingOrderController chargingOrderController;

    private final ChargingOrderRepository chargingOrderRepository;

    @Autowired
    public OrderProcessingService(HttpClientUtil httpClientUtil, ChargingOrderRepository chargingOrderRepository) {
        this.httpClientUtil = httpClientUtil;

        this.chargingOrderRepository = chargingOrderRepository;
    }

    /**
     * 处理订单更新消息
     */
    public void processOrderUpdate(String payload) {
        // 这里可以根据MQTT消息更新订单状态
        log.info("处理订单更新: {}", payload);

        // 示例：解析订单ID并处理
        // 实际应用中应该使用JSON解析payload
        String orderId = payload.split(":")[1];
        updateOrderStatus(orderId, 3);
    }

    /**
     * 处理充电站状态消息
     */
    public void processStationStatus(String payload) {
        log.info("处理充电站状态更新: {}", payload);

        // 这里可以处理充电站状态更新的业务逻辑
        // 例如：发送通知、更新数据库等
    }
    // 删除这行固定超时常量
    // private static final long TIMEOUT_THRESHOLD = 5 * 60 * 1000;

    // 超时时间（5分钟） - 删除这个注释212


    /**
     * 定期检查订单状态（使用Spring的Scheduled替代手动线程11）
     */
    /**
     * 每分钟检查一次订单状态，处理超时订单
     */
    @Scheduled(fixedDelay = 60000)  // 每分钟执行一次
    @ConditionalOnProperty(name = "task.checkAndUpdateOrders", havingValue = "true")
    public void checkAndUpdateOrders() {
        try {
            /*********************************充电桩断电退款start********************************************/
            List<ChargingOrder> chargingOrderList = chargingOrderService.getDieIcc();
            log.info("发现充电桩断电退款订单： {} 个", chargingOrderList.size());

            for (ChargingOrder order : chargingOrderList) {
                //计算退款金额
                BigDecimal refundAmount = calculateRefundAmount(order);
                // 调用退款服务
                boolean refundSuccess = paymentService.refund(
                        order.getOrderId(),
                        refundAmount
                );

                if (refundSuccess) {
                    log.info("订单退款成功: orderId={}, refundAmount={}", order.getId(), refundAmount);
                    // 更新订单退款信息
                    order.setRefundAmount(refundAmount);
                    order.setRefundTime(new Date());
                } else {
                    log.error("订单退款失败: orderId={}, refundAmount={}", order.getId(), refundAmount);
                }
                // 修改：使用OrderStatus.TIMEOUT.getCode()获取正确的已退款状态码4
                order.setStatus(OrderStatus.REFUNDED.getCode()); // 4-已退款
                int s = chargingOrderService.updateRefundOrder(order);
                if (s > 0) {
                    log.info("订单 {} 更新成功", order.getId());
                } else {
                    log.info("订单 {} 更新失败", order.getId());
                }
            }
            /*********************************充电桩断电退款end********************************************/


            log.debug("开始检查订单状态...");

            //
            List<ChargingOrder> paidWaitingOrders = chargingOrderRepository.findByStatusAndIsDeleted(1, 0);


            List<ChargingOrder> chargingOrders = chargingOrderRepository.findByStatusAndIsDeleted(2, 0);

            log.info("找到 {} 个已支付待充电的订单，{} 个充电中的订单",
                    paidWaitingOrders.size(), chargingOrders.size());

            // 只处理真正充电中的订单
            if (chargingOrders == null || chargingOrders.isEmpty()) {
                log.info("没有找到充电中的订单");
                return;
            }

            log.info("找到 {} 个充电中的订单", chargingOrders.size());
            long currentTime = System.currentTimeMillis();
            int updatedCount = 0;

            // 2. 检查每个订单是否超时
            for (ChargingOrder order : chargingOrders) {
                Date startTime = order.getStartTime();
                if (startTime != null) {
                    long startTimestamp = startTime.getTime();

                    // 获取用户预付的充电时长（分钟）
                    Integer chargingMinutes = order.getChargingMinutes();
                    if (chargingMinutes == null || chargingMinutes <= 0) {
                        chargingMinutes = 60; // 默认1小时
                    }

                    // 计算动态超时阈值：预付时长 + 10分钟缓冲时间
                    long dynamicTimeoutThreshold = (chargingMinutes + 10) * 60 * 1000L;

                    // 检查是否超过预付时长 + 缓冲时间
                    if (currentTime - startTimestamp >= dynamicTimeoutThreshold) {
                        log.info("订单超过预付时长，触发超时处理: orderId={}, 预付时长={}分钟, 实际充电时长={}分钟",
                                order.getId(), chargingMinutes, (currentTime - startTimestamp) / (60 * 1000));

                        // 设置结束时间
                        if (order.getEndTime() == null) {
                            order.setEndTime(new Date());
                            log.info("设置超时订单结束时间: orderId={}, endTime={}", order.getId(), order.getEndTime());
                        }

                        // 修复：使用calculateRefundAmount方法计算退款金额，而不是全额退款
                        BigDecimal refundAmount = calculateRefundAmount(order);

                        log.info("退款金额计算: 数据库金额={}元, 实际退款金额={}元", order.getPrepayAmount(), refundAmount);

                        // 调用退款服务
                        boolean refundSuccess = paymentService.refund(
                                order.getOrderId(),
                                refundAmount
                        );

                        if (refundSuccess) {
                            log.info("订单退款成功: orderId={}, refundAmount={}", order.getId(), refundAmount);
                            // 更新订单退款信息
                            order.setRefundAmount(refundAmount);
                            order.setRefundTime(new Date());
                        } else {
                            log.error("订单退款失败: orderId={}, refundAmount={}", order.getId(), refundAmount);
                        }

                        // 修改：使用OrderStatus.TIMEOUT.getCode()获取正确的超时状态码5
                        order.setStatus(OrderStatus.TIMEOUT.getCode()); // 5-超时
                        chargingOrderRepository.save(order);

                        updatedCount++;
                    }
                }
            }

            log.debug("订单状态检查完成，更新了 {} 个超时订单", updatedCount);
        } catch (Exception e) {
            log.error("检查订单状态时出错", e);
        }
    }

    /**
     * 计算退款金额
     * <p>
     * 退款规则：
     * 1. 开始充电后，30秒内断电退全款
     * 2. 充电超过设定时间的70%，不退款
     * 3. 充电大于30秒，小于预订时间的70%，按比例部分退款
     *
     * @param order 订单信息
     * @return 退款金额
     */
    private BigDecimal calculateRefundAmount(ChargingOrder order) {
        try {
            // 获取充电开始时间
            Date startTime = order.getStartTime();
            if (startTime == null) {
                log.warn("订单没有开始时间记录，将全额退款: orderId={}", order.getId());
                return order.getPrepayAmount();
            }

            // 计算已充电时间（秒）
            long chargingTimeInSeconds = (System.currentTimeMillis() - startTime.getTime()) / 1000;

            // 获取预设充电时间（分钟）
            int plannedTimeInMinutes = order.getChargingMinutes() != null ?
                    order.getChargingMinutes() : 60; // 默认1小时

            // 转换为秒
            long plannedTimeInSeconds = plannedTimeInMinutes * 60;

            // 获取预付金额
            BigDecimal prepayAmount = order.getPrepayAmount();
            if (prepayAmount == null) {
                log.warn("订单没有预付金额记录，无法计算退款: orderId={}", order.getId());
                return BigDecimal.ZERO;
            }

            // 规则1: 开始充电后，30秒内断电退全款
            if (chargingTimeInSeconds <= 30) {
                log.info("充电时间不足30秒，全额退款: orderId={}, chargingTime={}秒",
                        order.getId(), chargingTimeInSeconds);
                return prepayAmount;
            }

            // 规则2: 充电超过设定时间的70%，不退款
            long seventyPercentTime = (long) (plannedTimeInSeconds * 0.7);
            if (chargingTimeInSeconds >= seventyPercentTime) {
                log.info("充电时间已超过预设时间的70%，不退款: orderId={}, chargingTime={}秒, 预设时间70%={}秒",
                        order.getId(), chargingTimeInSeconds, seventyPercentTime);
                return BigDecimal.ZERO;
            }

            // 规则3: 充电大于30秒，小于预订时间的70%，按比例部分退款
            // 计算剩余时间比例
            BigDecimal remainingTimeRatio = BigDecimal.valueOf(plannedTimeInSeconds - chargingTimeInSeconds)
                    .divide(BigDecimal.valueOf(plannedTimeInSeconds), 4, BigDecimal.ROUND_HALF_UP);

            // 计算退款金额
            BigDecimal refundAmount = prepayAmount.multiply(remainingTimeRatio);

            log.info("按比例退款: orderId={}, 充电时间={}秒, 预设时间={}秒, 退款比例={}%, 退款金额={}元",
                    order.getId(), chargingTimeInSeconds, plannedTimeInSeconds,
                    remainingTimeRatio.multiply(BigDecimal.valueOf(100)).setScale(2),
                    refundAmount.setScale(2, BigDecimal.ROUND_HALF_UP));

            return refundAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            log.error("计算退款金额失败", e);
            return BigDecimal.ZERO;
        }
    }


    /**
     * 更新订单状态
     */
    private void updateOrderStatus(String orderId, int status) {
        // 这里可以实现通过HTTP或直接操作数据库更新订单状态
        // 示例HTTP请求：
        // httpClientUtil.doPost(.111..)
        log.info("更新订单状态: orderId={}, status={}", orderId, status);
    }

    // 支付成功但未开始充电的超时时间（3分钟）
    private static final long PAYMENT_TO_CHARGING_TIMEOUT = 3 * 60 * 1000;
    private int refundedCount = 0; // 添加退款计数器

    /**
     * 每分钟检查一次已支付但未开始充电的订单，处理超时未充电订单的自动退款
     */
    @Scheduled(fixedDelay = 60000)  // 每分钟执行一次
    @ConditionalOnProperty(name = "task.checkPaidNotChargingOrders", havingValue = "true")
    public void checkPaidNotChargingOrders() {
        try {
            log.debug("开始检查已支付但未开始充电的订单...");

            // 修复：添加is_deleted=0过滤条件
            List<ChargingOrder> paidOrders = chargingOrderRepository.findByStatusAndStartTimeIsNullAndIsDeleted(
                    OrderStatus.PAID.getCode(), 0);  // 0表示未删除

            if (paidOrders == null || paidOrders.isEmpty()) {
                log.info("没有找到已支付但未开始充电的订单");
                return;
            }

            log.info("找到 {} 个已支付但未开始充电的订单", paidOrders.size());
            long currentTime = System.currentTimeMillis();
            int refundedCount = 0;

            for (ChargingOrder order : paidOrders) {
                // 检查order_id是否为空
                if (order.getOrderId() == null || order.getOrderId().trim().isEmpty()) {
                    log.debug("跳过没有orderid的历史订单: id={}", order.getId());
                    continue;
                }

                // 🔧 新增：检查订单是否已经退款过
                if (order.getRefundAmount() != null && order.getRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
                    log.debug("订单已退款，跳过: orderId={}, refundAmount={}", order.getOrderId(), order.getRefundAmount());
                    continue;
                }

                // 🔧 新增：检查订单是否已经被标记为删除
                if (order.getIsDeleted() != null && order.getIsDeleted() == 1) {
                    log.debug("订单已删除，跳过: orderId={}", order.getOrderId());
                    continue;
                }

                // 方案1：使用支付时间而不是updateDate
                Date paymentTime = order.getPaymentTime();
                if (paymentTime != null) {
                    long paymentTimestamp = paymentTime.getTime();
                    if (currentTime - paymentTimestamp >= PAYMENT_TO_CHARGING_TIMEOUT) {
                        // 触发退款
                        log.info("订单支付超时，开始退款: orderId={}, 支付时间={}, 超时时长={}分钟",
                                order.getOrderId(), paymentTime,
                                (currentTime - paymentTimestamp) / (60 * 1000));

                        // 在checkPaidNotChargingOrders方法中
                        try {
                            // 计算退款金额（直接使用预付金额）
                            BigDecimal refundAmount = order.getPrepayAmount();

                            // 修复：调用退款服务时使用业务订单号
                            boolean refundSuccess = paymentService.refund(
                                    order.getOrderId(),  // 使用业务订单号而不是主键ID
                                    refundAmount
                            );

                            if (refundSuccess) {
                                // 更新订单状态为已退款
                                order.setStatus(OrderStatus.REFUNDED.getCode());
                                order.setRefundAmount(refundAmount);
                                order.setUpdateDate(new Date());
                                chargingOrderRepository.save(order);

                                refundedCount++;
                                log.info("订单退款成功: businessOrderId={}, 退款金额={}",
                                        order.getOrderId(), refundAmount);
                            } else {
                                log.error("订单退款失败: businessOrderId={}", order.getOrderId());
                            }
                        } catch (Exception e) {
                            log.error("处理订单退款时出错: businessOrderId={}", order.getOrderId(), e);
                        }
                    }
                } else {
                    // 如果没有支付时间，使用updateDate作323为备选方案
                    Date updateDate = order.getUpdateDate();
                    if (updateDate != null) {
                        long updateTimestamp = updateDate.getTime();
                        if (currentTime - updateTimestamp >= PAYMENT_TO_CHARGING_TIMEOUT) {
                            // 同样的退款逻辑...
                        }
                    }
                }
            }

            log.debug("已支付未充电订单检查完成，退款处理了 {} 个订单", refundedCount);
        } catch (Exception e) {
            log.error("检查已支付未充电订单时出错", e);
        }
    }


    /**
     * 手动触发订单退款
     *
     * @param orderId 订单ID
     * @return 退款是否成功
     */
    // 在manualRefundOrder方法中
    public boolean manualRefundOrder(Long orderId) {
        try {
            ChargingOrder order = chargingOrderRepository.findById(orderId).orElse(null);
            if (order == null) {
                log.error("未找到订单: orderId={}", orderId);
                return false;
            }

            // 只有已支付或充电中的订单可以退款
            if (order.getStatus() != OrderStatus.PAID.getCode() &&
                    order.getStatus() != OrderStatus.CHARGING.getCode()) {
                log.error("订单状态不允许退款: orderId={}, status={}", orderId, order.getStatus());
                return false;
            }

            // 计算退款金额
            BigDecimal refundAmount;
            if (order.getStatus() == OrderStatus.PAID.getCode()) {
                // 已支付未充电，全额退款
                refundAmount = order.getPrepayAmount();
            } else {
                // 充电中，按比例退款
                refundAmount = calculateRefundAmount(order);
            }

            // 修复：调用退款接口时使用业务订单号121
            boolean refundSuccess = paymentService.refund(order.getOrderId(), refundAmount);
            if (refundSuccess) {
                order.setStatus(ChargingOrder.STATUS_REFUNDED);
                // 🔧 需要添加：设置退款金额和退款时间
                order.setRefundAmount(refundAmount);
                order.setRefundTime(new Date());
                order.setIsDeleted(1);
                order.setUpdateDate(new Date());
                chargingOrderRepository.save(order);

                log.info("手动退款成功: primaryId={}, businessOrderId={}, refundAmount={}", orderId, order.getOrderId(), refundAmount);
                return true;
            } else {
                log.error("手动退款失败: primaryId={}, businessOrderId={}", orderId, order.getOrderId());
                return false;
            }
        } catch (Exception e) {
            log.error("手动退款处理出错: orderId={}", orderId, e);
            return false;
        }
    }


    /**
     * 每5秒检查一次订单状态，处理发送开始充电指令失败订单
     */
    @Scheduled(fixedDelay = 5000)  // 每分钟执行一次
    @ConditionalOnProperty(name = "task.reStartChargingOrders", havingValue = "true")
    public void reStartChargingOrders() throws InterruptedException {
        log.debug("开始检测未启动订单");
        List<ChargingOrder> paidWaitingOrders = chargingOrderRepository.findByStatusAndIsDeleted(1, 0);
        for (ChargingOrder order : paidWaitingOrders) {
            Date a0 = new Date();
            Date a1 = new Date();
            a1.setSeconds(a1.getSeconds() - 5);
            Date a2 = new Date();
            a2.setSeconds(a2.getSeconds() - 30);
            log.debug("开始查询{}-{}之间未启动订单", a1, a2);
            if (order.getPaymentTime().before(a1) && order.getPaymentTime().after(a2)) {
                sleep(200);
                log.debug("发现未启动订单，订单号为：{};支付时间为：{};当前时间为：{}", order.getOrderId(), order.getPaymentTime(), a0);
                //重新发启动指令
                OrderEntity orderx = orderService.getOrderById(order.getId());
                if (orderx.getStatus() == OrderStatus.PAID.getCode()) {
                    OrderEntity orders = orderService.getOrderByOrderNo(order.getOrderId());
                        chargingOrderController.sendStartChargingCommand(orders);
                }
            }
        }
    }
}